/**
##############################################################################
#
# Copyright (C) 2021 企慧蚁 Grit<dooms21day@163.com>
# All Rights Reserved
#
##############################################################################
 */
odoo.define('iant_dynamic_list_form.ListRender', function(require) {
    "use strict";

    var session = require('web.session');
    var SortDropdown = require('iant_dynamic_list_form.SortDropdown');
    var uid = session.uid;
    var dom = require('web.dom');
    var ListRenderer = require('web.ListRenderer');

    // 预置的列宽度，没有设置时取以下预置数据。字段类型： 宽度px
    const fieldTypeDefaultWidths = {
        boolean: 55,
        date: 130,
        datetime: 205,
        float: 92,
        integer: 74,
        monetary: 104
    };
    // 特定字段的默认宽度,优先级比fieldTypeDefaultWidths高. 字段名： 宽度px
    const fieldsDefaultWidths = {
        sequence: 20,
        product_id: 400,
        partner_id: 400,
        nd_producer_id: 400
    };
    // 除以上的其他列的默认宽度
    const columnDefaultWidth = 150;
    // 除了bool外的最小宽度
    // const columnMinWidth = 90;
    // 需要排除设置最小宽度的字段类型
    // const columnMinExclude = ['boolean'];

    ListRenderer.include({

        events: _.extend({}, ListRenderer.prototype.events, {
            'dblclick tbody tr': '_onDblRowClicked'
        }),

        ensureEnv: function () {
            var self = this;
            var success = function (data) {
                if (data.viewId) {
                    this.viewId = data.viewId;
                }
                if (data.model) {
                    this.configModel = data.model;
                }
                if (data.actionId) {
                    this.actionId = data.actionId;
                }
            };
            this.trigger_up('get_env', {onSuccess: success.bind(self)});
        },

        _getFormField: function () {
            var form_field = '';
            var parent = this.getParent();
            if (parent.formatType && parent.formatType == 'one2many') {
                form_field = parent.name;
            }
            return form_field;
        },

        willStart: function(){
    		this.formField = this._getFormField();
    		this.ensureEnv();
    		this._processColumns({});
    		return this._super.apply(this,arguments);
        },

        _set_table_width: function(){
            var $table = this.$el.find(".o_list_view");
            $table.css('table-layout','fixed');
            var thead_width = _.reduce(_.map(this.columns, col=>col.attrs.width || 0), (tw,w)=>tw+w);
            if (thead_width > 0){
                $table.css("width", String(thead_width) + "px")
            }
        },

        /*
        * 设置列宽
        * */
        _renderHeaderCell: function (node) {
            var $th = this._super(...arguments);
            var node_name = node.attrs.name;
            var column = _.filter(this.columns, col => col.attrs.name===node_name);
            if (column.length > 0){
                var field_width = column[0].attrs.width || columnDefaultWidth;
                field_width > 0 && $th.width(field_width);
            }

            if (!node.attrs.widget && node.attrs.name &&
                this.state.fields[node.attrs.name] &&
                this.state.fields[node.attrs.name].type === 'many2one') {
                // No explicit widget provided on a many2one field,
                // force `many2one` widget
                node.attrs.widget = 'many2one';
            }
            return $th;
        },

        _processColumns: function (columnInvisibleFields) {
            this._super.apply(this, arguments);
            if (this.configModel){
                var configColumns = this._getColumnByConfig();
                if (_.size(configColumns)) {
                    this.columns = configColumns;
                }
            }
        },

        _get_column_width(column_name, default_width){
            var column_width = default_width || 0;
            var column_field = this.state.fields[column_name];
            if (!Boolean(column_width)){
                column_width = _.has(fieldsDefaultWidths, column_name) ? fieldsDefaultWidths[column_name] : column_width
            }
            if (!Boolean(column_width) && _.has(column_field, 'type')){
                column_width = _.has(fieldTypeDefaultWidths, column_field.type) ? fieldTypeDefaultWidths[column_field.type] : column_width
            }
            return column_width || columnDefaultWidth;
        },

        _getColumnByConfig: function () {
            var columns = [];
            var self = this;
            var processed_columns = [];
            if (this.configModel) {
                var sortConfigs = this.configModel.getSortFieldConfig(this.formField, this.state.model);
                _.each(sortConfigs, function (config) {
                    var data = config.data;
                    processed_columns.push(data.name);
                    if (!data.invisible) {
                        var column = _.chain(self.columns).filter(function (col) {
                            return col.attrs.name == data.name;
                        }).first().value();
                        var column_width = self._get_column_width(data.name, data.width);
                        if (column) {
                            column['attrs']['width'] = column_width;
                            column['attrs']['string'] = self._getColumnString(column, "");
                            columns.push(column);
                        }
                        else {
                            columns.push({
                                tag: 'field',
                                children: [],

                                attrs: {
                                    name: data.name,
                                    width: column_width,
                                    string: data.string,
                                    widget: self.state.fields[data.name].type
                                }
                            })
                        }
                    }


                });

            }
            
            _.each(self.columns, function (col) {
               if (processed_columns.indexOf(col.attrs.name) === -1){
                   var col_width = self._get_column_width(col.attrs.name, col.attrs.width);
                   col.attrs.width = col_width;
                   columns.push(col);
               }
            });
            return columns;
        },

        getFieldsData: function () {
            var self = this;
            var configModel = this.configModel;
            var fieldConfigId = configModel.fieldConfigId;
            var fieldsData = [];
            var names = [];
            var proms = [];
            if (!configModel || !fieldConfigId) {
                return Promise.resolve(fieldsData);
            }
            // 配置的列
            var sortConfigs = configModel.getSortFieldConfig(this.formField, this.state.model);
            //所有可显示的按照顺序排列到最前面。set_config_name
            if (_.size(sortConfigs)) {
                _.each(sortConfigs, function (config) {
                    names.push(config.data.name);
                    fieldsData.push({
                        id: config.id,
                        width: self._get_column_width(config.data.name, config.data.width),
                        invisible: config.data.invisible,
                        name: config.data.name,
                        string: config.data.string,
                        sequence: config.sequence
                    });
                });

            }
            var maxItem = _.max(fieldsData, function (item) {
                return item.sequence
            });
            // 最大的排序编号
            var sequence = (maxItem && maxItem.sequence) || 0;
            // 默认显示的列
            _.each(self.columns, function (col) {
                if (_.size(_.filter(names, function (item) {
                    return item == col.attrs.name
                }))) {
                    return;
                }
                names.push(col.attrs.name);
                proms.push(configModel.addDefaultRecord(fieldConfigId).then(function (recordId) {
                    var record = configModel.localData[recordId];
                    var changes = {};
                    changes.name = col.attrs.name;
                    changes.form_field = self.formField;
                    changes.view_id = self.viewId;
                    changes.act_id = self.actionId;
                    changes.user_id = uid;
                    changes.width = self._get_column_width(col.attrs.name, col.attrs.width);
                    changes.res_model = self.state.model;
                    changes.string = self._getColumnString(col, {});
                    changes.is_field = (col.tag == 'field');
                    changes.invisible = false;
                    changes.sequence = sequence;
                    configModel.notifyChanges(recordId, changes);
                    sequence++;
                    fieldsData.push(_.extend({}, {id: recordId}, changes));
                }));
            });
            _.each(self.state.fields, function (value, key) {
                if (_.size(_.filter(names, function (item) {
                    return item == key
                }))) {
                    return;
                }
                names.push(key);
                proms.push(configModel.addDefaultRecord(fieldConfigId).then(function (recordId) {
                    var record = configModel.localData[recordId];
                    var changes = {};
                    changes.name = key;
                    changes.form_field = self.formField;
                    changes.view_id = self.viewId;
                    changes.act_id = self.actionId;
                    changes.user_id = uid;
                    changes.string = self._getColumnString({}, key);
                    changes.is_field = true;
                    changes.invisible = true;
                    changes.res_model = self.state.model;
                    changes.sequence = sequence;
                    changes.width = self._get_column_width(key);
                    sequence++;
                    configModel.notifyChanges(recordId, changes);
                    fieldsData.push(_.extend({}, {id: recordId}, changes));

                }));
            });
            return Promise.all(proms).then(function () {
                return fieldsData;
            });
        },

        getListData: function () {
            var self = this;
            var listData = [];
            var configModel = this.configModel;
            var listConfigId = configModel.listConfigId;
            if (!configModel || !listConfigId) {
                return Promise.resolve(listData);
            }

            var configs = configModel.getListConfig(this.formField, this.state.model);
            if (_.size(configs)) {
                return Promise.resolve().then(function () {
                    return _.map(configs, function (config) {
                        return {
                            id: config.id,
                            name: config.data.name,
                            string: config.data.string,
                            value: config.data.value,
                            form_field: config.data.form_field
                        };
                    });
                });
            } else {
                return configModel.addDefaultRecord(listConfigId).then(function (recordId) {
                    var record = configModel.localData[recordId];
                    var changes = {};
                    changes.name = 'limit';
                    changes.form_field = self.formField;
                    changes.view_id = self.viewId;
                    changes.act_id = self.actionId;
                    changes.user_id = uid;
                    //changes.string = "page";
                    changes.res_model = self.state.model;
                    changes.value = 80;
                    configModel.notifyChanges(recordId, changes);
                    listData.push(_.extend({}, {id: recordId}, changes));
                    return listData;
                });
            }

        },

        /*
        * 获取列名称
        * param column: 显示列的对应参数，如果有单独设置则在当前已经用设置的值进行更新，
        * 即当前column为指定用户的特有设置值
        * param field: 实际字段值，取自系统原数据
        * */
    	_getColumnString:function(column, field_name){
    	    var self = this;
    	    var fieldName = _.has(column.attrs, 'name') ? column.attrs.name : field_name;
    	    var string;
            var field = self.state.fields[fieldName];
            var fieldInfo = self.state.fieldsInfo.list[fieldName];
            if (_.has(column.attrs, 'widget')) {
                string = fieldInfo.Widget.prototype.description;
            }
            if (!Boolean(string)) {
                // 在列是button时，<button name="sss" icon="fa fa-history"/>field不存在
                if (field){
                    string = _.has(column.attrs, 'string') ? column.attrs.string : field.string;
                } else {
                    string = _.has(column.attrs, 'string') ? column.attrs.string : '未命名';
                }
            }
            return string;
    	},

        _renderView: function () {
            var self = this;
            this.currentRow = null;
            self.ensureEnv();
            return this._super.apply(this, arguments).then(function () {
                self._set_table_width();
                self._onRendererDomReady();
                self.getFieldsData().then(function (data) {
                    self.getListData().then(function (listData) {
                        var dropdown = new SortDropdown(self, {
                            state: data,
                            listConfig: listData,
                            $menu_id: _.uniqueId("drop_menu_")
                        });
                        dropdown.appendTo(self.$('.o_list_view'));
                    });

                });

            });
        },

        /*
        * --------------------------------------------------------------
        * 列点击需要双击才能进入详情
        * --------------------------------------------------------------
        * */
        _onDblRowClicked: function (ev) {
            if (!ev.target.closest('.o_list_record_selector') && !$(ev.target).prop('special_click')) {
                var id = $(ev.currentTarget).data('id');
                if (id) {
                    this.trigger_up('open_record', {
                        id: id,
                        target: ev.target
                    });
                }
            }
        },

        _onRowClicked: function (ev) {
            if (!ev.target.closest('.o_list_record_selector') && !$(ev.target).prop('special_click')) {
                ev.stopPropagation();
            }
        },

        /*
        * --------------------------------------------------------------
        * 列表页脚统计行，修改数值默认行为为sum
        * --------------------------------------------------------------
        * */
        _computeColumnAggregates: function (data, column) {
            var attrs = column.attrs;
            var field = this.state.fields[attrs.name];
            if (!field) {
                return;
            }
            var type = field.type;
            var excluded_fields = ['sequence', 'id'];
            if (_.indexOf(excluded_fields, attrs.name) !== -1){
                return;
            }
            if (type !== 'integer' && type !== 'float' && type !== 'monetary') {
                return;
            }
            var func = (attrs.sum && 'sum') || (attrs.avg && 'avg') ||
                (attrs.max && 'max') || (attrs.min && 'min') || 'sum';
            if (func) {
                var count = 0;
                var aggregateValue = (func === 'max') ? -Infinity : (func === 'min') ? Infinity : 0;
                _.each(data, function (d) {
                    count += 1;
                    var value = (d.type === 'record') ? d.data[attrs.name] : d.aggregateValues[attrs.name];
                    if (func === 'avg') {
                        aggregateValue += value;
                    } else if (func === 'sum') {
                        aggregateValue += value;
                    } else if (func === 'max') {
                        aggregateValue = Math.max(aggregateValue, value);
                    } else if (func === 'min') {
                        aggregateValue = Math.min(aggregateValue, value);
                    }
                });
                if (func === 'avg') {
                    aggregateValue = count ? aggregateValue / count : aggregateValue;
                }
                column.aggregate = {
                    help: attrs[func],
                    value: aggregateValue,
                };
            }
        },

        /*
        * 重载
        * 在实际设置宽度已超过table宽度时，重新设置table宽度
        * */
        on_attach_callback: function () {
            this._onRendererDomReady();
        },

        _onRendererDomReady : function () {
            var self = this;
            function sticky(){
                self.$el.find("table.o_list_view").each(function () {
                    $(this).stickyTableHeaders({scrollableArea:  $(".o_content")[0], fixedOffset: 0.01});
                });
            }

            function fix_body(position){
                 $("body").css({
                   'position': position,
                });
            }

            if(self.$el){
                if(!(this.getParent().$el.hasClass("o_field_one2many")|| this.getParent().$el.hasClass("o_field_many2many"))){
                    sticky();
                    fix_body("fixed");
                    self.$el.css("overflow-x","visible");
                }
                else{
                    fix_body("relative");
                }
            }
            $("div[class='o_sub_menu']").css("z-index",4);
        },


    });

});